package demo.maven.bean.factory;

import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @author peter
 * @date 2021/12/4 上午1:54
 */
@Slf4j
public class BeanFactory {

    private static String beanProperties = "bean.properties";

    // 定义一个 Properties 对象
    private static Properties properties = null;

    // 定一个Beans存放我们要创建的对象, 我们称为容器
    private static Map<String, Object> beans;

    static {
        try {
            properties = new Properties();
            // 读取配置
            InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream(beanProperties);
            // 加载配置
            properties.load(is);

            beans = new HashMap<String, Object>();

            Enumeration<Object> keys = properties.keys();
            while (keys.hasMoreElements()) {
                // 取出每一个key
                String key = keys.nextElement().toString();
                // 获取beanPath
                String beanPath  = properties.getProperty(key);
                // 反射创建对象
                Object bean = Class.forName(beanPath).newInstance();
                // 把key和value放入到bean中
                beans.put(key, bean);
            }

            log.info("load config once");
        } catch (Exception e) {

            e.printStackTrace();
            throw new ExceptionInInitializerError(String.format("%s 初始化失败 --> %s", beanProperties, e.getMessage()));
        }
    }

    /**
     * 获取Bean对象
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName) {
        return getSingletonBean(beanName);
    }

    /**
     * 优化工厂方法
     * @param beanName
     * @return
     */
    public static Object getSingletonBean(String beanName) {
        return beans.get(beanName);
    }

    /**
     * 工厂方法获取Bean
     * @param beanName
     * @return
     */
    public static Object getFactoryBean(String beanName) {

        // 获取Bean映射
        String beanPath = properties.getProperty(beanName);
        Object obj = null;
        try {
            // 反射获取对象
            obj = Class.forName(beanPath).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return obj;
    }
}
